package com.woniu.controller;

import com.alibaba.fastjson.JSONObject;
import com.woniu.entity.PageData;
import com.woniu.entity.Result;
import com.woniu.entity.dto.CollectDTO;
import com.woniu.entity.dto.LoginAdminDTO;
import com.woniu.entity.dto.LoginUserDTO;
import com.woniu.entity.vo.UserLoginVO;
import com.woniu.pojo.Admin;
import com.woniu.pojo.User;
import com.woniu.service.ICollectService;
import com.woniu.service.ITrainingService;
import com.woniu.service.IUserService;
import com.woniu.util.Md5Utils;
import com.woniu.util.MobileUtil;
import com.woniu.util.SendSmsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Controller
@Api(tags = "用户信息")
@RequestMapping("/user")
@Slf4j
public class UserController extends BaseController {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IUserService userService;
    @Autowired
    private ITrainingService trainingService;
    @Autowired
    private ICollectService collectService;

    @Value("${gitee.clientID}")
    private String clientID;

    @Value("${gitee.clientSecret}")
    private String clientSecret;

    @Value("${gitee.giteeReturnUrl}")
    private String giteeReturnUrl;


    @GetMapping("/sendSms/{mobile}/{action}")
    @ResponseBody
    @ApiOperation("手机号码及发送短信验证")
    public Result sendSmsCode(@PathVariable String mobile, @PathVariable String action) {
        //校验手机号码是否正确
        boolean flag = MobileUtil.checkChinaMobile(mobile);
        if (!flag) {
            return error();
        }
        // 判断该手机号码该在场景有没有没有过期的短信，有过期的短信，不发了。 如果没有，发送短信
        Object redisCode = redisTemplate.opsForValue().get("code_" + action + "_" + mobile);
        if (redisCode != null) {
            return error("验证码已发送，请稍后再试");
        }
        //判断滑动验证模块的次数
        Integer slideCount = (Integer) redisTemplate.opsForValue().get("slideCount" + action + "_" + mobile);
        if (slideCount != null) {
            System.out.println(slideCount);
            if (slideCount == 3) {
                return error("开启滑动模块");
            }
        }
        // 判断该手机号码在该场景的次数有没有用完
        Integer codeCount = (Integer) redisTemplate.opsForValue().get("code_count_" + action + "_" + mobile);
        if (codeCount == null) {
            codeCount = 0;
        }
        if (codeCount == 3) {
            return error("今天的次数已经用完了");
        }
        // 发送的次数需要加1
        redisTemplate.opsForValue().set("code_count_" + action + "_" + mobile, codeCount + 1);

        //生成短信验证码
        String code = SendSmsUtil.getRandomNum(4);

        redisTemplate.opsForValue().set("code" + action + "_" + mobile, code, 1 * 60, TimeUnit.SECONDS);

        //调用工具类发送短信
        SendSmsUtil.sendSms(mobile, code);
        System.out.println(code);
        // 5. 响应数据
        return success();
    }

    @PostMapping("/register/{action}")
    @ResponseBody
    @ApiOperation("注册")
    public Result register(@PathVariable String action, @RequestBody LoginUserDTO loginUserDTO) {
        User user = new User();
        //判断短信验证码-是否为空
        String code = loginUserDTO.getCode();
        System.out.println(code);
        if (StringUtils.isEmpty(code)) {
            return error();
        }
        //判断验证码是否有值
        String redisCode = (String) redisTemplate.opsForValue().get("code" + action + "_" + loginUserDTO.getMobile());
        if (redisCode == null || !redisCode.equals(code)) {

            //注册的滑动验证次数
            Integer slide = (Integer) redisTemplate.opsForValue().get("slideCount" + action + "_" + loginUserDTO.getMobile());
            if (slide == null) {
                slide = 0;
            }
            redisTemplate.opsForValue().set("slideCount" + action + "_" + loginUserDTO.getMobile(), slide + 1);
            return error("验证码错误或者不存在");
        }
        // 删除session中的验证码
        redisTemplate.delete("code_register_" + loginUserDTO.getMobile());

        if (loginUserDTO.getPassword() == null) {
            return error("密码不能为空");
        }
        //调用service的注册方法，进行注册（保存）/MD5加密码
        userService.register(loginUserDTO);
        return success();
    }

    @PostMapping("/login/{action}")
    @ResponseBody
    @ApiOperation("手机号码验证登陆")
    public Result login(@PathVariable String action, @RequestBody LoginUserDTO loginUserDTO, HttpSession session) {
        // 先判断验证码是否正确
        System.out.println(loginUserDTO);
        String redisCode = (String) redisTemplate.opsForValue().get("code" + action + "_" + loginUserDTO.getMobile());
        System.out.println("code" + action + "_" + loginUserDTO.getMobile());
        System.out.println(redisCode);
        if (redisCode == null || !redisCode.equals(loginUserDTO.getCode())) {

            //滑动验证第三次错误开启
            Integer slide = (Integer) redisTemplate.opsForValue().get("slideCount" + action + "_" + loginUserDTO.getMobile());
            if (slide == null) {
                slide = 0;
                redisTemplate.opsForValue().set("slideCount" + action + "_" + loginUserDTO.getMobile(), slide + 1);
            } else if (slide == 3) {
                return error("开启滑块");
            }

            return error("验证码错误");
        }
        // 判断手机号码是否已经注册（根据手机号码查询用户信息）
        UserLoginVO userLoginVO = userService.login(loginUserDTO.getMobile());
        System.out.println(userLoginVO);
        if (userLoginVO == null) {
            return error("该账号不存在");
        }
        if (loginUserDTO.getUserType() == 1) {
            return error("该账号已经封禁");
        }
        if (loginUserDTO.getMobile() == null) {
            return error("请输入手机号");
        }
        // 如果登录成功，将用户的信息保存到session中
        User user = userService.userIsExist(loginUserDTO.getName(), loginUserDTO.getPassword());
        session.setAttribute("user", user);
        // 响应结果
        return success();
    }

    @PostMapping("/pwd/{action}")
    @ResponseBody
    @ApiOperation("用户密码登陆")
    public Result login(@RequestBody LoginUserDTO loginUserDTO, @PathVariable String action, HttpSession session) {
        log.debug("进入的了登录的方法，用户名为{},密码为{}", loginUserDTO.getName(), loginUserDTO.getPassword());
        User user = userService.userIsExist(loginUserDTO.getName(), loginUserDTO.getPassword());
        String pwdCountTime = (String) redisTemplate.opsForValue().get("pwd_times" + action + "_" + loginUserDTO.getName());
        //获取redis的剩余时间
        Long expire = redisTemplate.opsForValue().getOperations().getExpire("pwd_times" + action + "_" + loginUserDTO.getName(), TimeUnit.SECONDS);
        if (pwdCountTime != null) {
            return error("密码输入错误上限，请在等待" + expire + "秒。");
        }
        if (user == null) {
            // 判断该密码在该场景的次数有没有用完
            Integer pwdCount = (Integer) redisTemplate.opsForValue().get("pwd_count_" + action + "_" + loginUserDTO.getName());
            if (pwdCount == null) {
                pwdCount = 0;
            }

            if (pwdCount >= 0 || pwdCount < 5) {

                redisTemplate.opsForValue().set("pwd_count_" + action + "_" + loginUserDTO.getName(), pwdCount + 1);
            }
            if (pwdCount >= 5) {
                redisTemplate.opsForValue().set("pwd_times" + action + "_" + loginUserDTO.getName(), "Times", 10 * 60, TimeUnit.SECONDS);
                return error("密码输入错误上限");
            }
            return error("密码错误");
        } else {

            if (user.getUserType() == 1) {
                return error("该用户已被封禁");
            }
            session.setAttribute("user", user);
        }
        return success();
    }


    @GetMapping("/loginout")
    @ApiOperation("注销登录")
    public Result loginOut(HttpSession session) {
        session.removeAttribute("user"); //移除保存在session中的用户信息
        session.invalidate(); //失效
        return new Result(true, "注销成功！");
    }

    @GetMapping("/searchOne/{id}")
    @ApiOperation("根据Id查询用户信息")
    @ResponseBody
    public Result searchOne(@PathVariable Integer id) {

        User user = userService.searchOne(id);

        log.info("查询Id = {} 的用户信息", id);
        return toDataResult(user);
    }

    /*修改个人主页上的信息 修改头像*/
    @PostMapping("/updateOne")
    @ApiOperation("修改用户信息")
    @ResponseBody
    public Result updateOne(@RequestBody User user) {

        Integer flag = userService.updateOne(user);

        log.info("修改Id = {} 的用户信息", user.getId());
        return toResult(flag);
    }

    /*修改密码*/
    @PostMapping("/update/password/{id}")
    @ApiOperation("修改用户密码")
    @ResponseBody
    public Result updatePassword(@PathVariable Integer id,
                                 @RequestParam String oldPassword,
                                 @RequestParam String newPassword) {
        Integer flag = userService.updatePassword(id, oldPassword, newPassword);
        return toResult(flag);
    }

    @PostMapping("/searchCollect/{currentPage}/{pageSize}")
    @ApiOperation("根据用户id查询用户收藏")
    @ResponseBody
    public Result searchCollect(@PathVariable Integer currentPage,
                                @PathVariable Integer pageSize,
                                @RequestBody CollectDTO collectDTO) {

        PageData pageData = collectService.searchCollect(currentPage, pageSize, collectDTO);
        return toDataResult(pageData);
    }

    @PostMapping("/searchHistory/{currentPage}/{pageSize}")
    @ApiOperation("根据用户id查询用户浏览记录")
    @ResponseBody
    public Result searchHistory(@PathVariable Integer currentPage,
                                @PathVariable Integer pageSize,
                                @RequestBody CollectDTO collectDTO) {

        PageData pageData = collectService.searchHistory(currentPage, pageSize, collectDTO);
        return toDataResult(pageData);
    }

    @GetMapping("/toAuth")
    @ApiOperation("第三方授权地址")
    public String giteeToAuth() throws UnsupportedEncodingException {
        // 拼接gitee的授权地址
        String url = "https://gitee.com/oauth/authorize?response_type=code" +
                "&client_id=" + clientID +
                "&redirect_uri=" + URLEncoder.encode(giteeReturnUrl, "UTF-8") +
                "&scope=user_info";
        // 重定向到gitee的授权地址
        return "redirect:" + url;
    }

    @GetMapping("/third")
    @ApiOperation("第三方获取用户信息")
    public String third(HttpServletRequest request) throws IOException {
        // 1. 获取用户授权之后返回的code
        String code = request.getParameter("code");
        log.debug("gitee返回的code为：{}", code);
        // 2. 根据返回的code去gitee获取授权码AccessToken
        String url = "https://gitee.com/oauth/token?grant_type=authorization_code" +
                "&client_id=" + clientID +
                "&client_secret=" + clientSecret +
                "&code=" + code +
                "&redirect_uri=" + giteeReturnUrl;
        // 调用工具类获取AccessToken
        JSONObject jsonObject = GiteeHttpClient.getAccessToken(url);
        String accessToken = jsonObject.getString("access_token");
        log.debug("gitee返回的accessToken为：{}", accessToken);
        // 3. 根据AccessToken去gitee获取用户的信息
        url = "https://gitee.com/api/v5/user?access_token=" + accessToken;
        JSONObject userInfo = GiteeHttpClient.getUserInfo(url);
        // 获取到用户信息，就已经表明gitee的账号是正确，可以授权本地的用户进行登录
        log.debug("根据accessToken获取gitee账号的信息为：{}", userInfo);

        String giteeId = userInfo.getString("id");
        UserLoginVO userLoginVO = userService.getByOpenId(giteeId);
        if (userLoginVO == null) {
            log.debug("该gitee账号还没绑定平台跳转到登录页面");
            return "redirect:http://localhost/user/login";
        }
        request.getSession().setAttribute("loginUser", userLoginVO);
        // 重定向到首页
        return "redirect:http://localhost/index";
    }
}

